home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / stdwin / Ports / mac / argcargv_ae.c < prev    next >
Text File  |  1995-12-21  |  6KB  |  244 lines

  1. /*
  2. ** argcargv_ae.c - Attempt to construct argc and argv by using apple events.
  3. **
  4. ** Needed because the old argcargv.c stopped working on the PowerPC mac.
  5. **
  6. ** This glue code was put together by Jack, mainly from information glanced from
  7. ** the mac programmers FAQ (where some of the code comes from, too) and from IM vol VI.
  8. ** The FAQ code, by the way, was dead wrong and needed quite a bit of polishing up.
  9. ** It uses high-level events and such to simulate argc/argv. This does mean, however,
  10. ** that the program can expect unexpected high-level events while it is running. It's
  11. ** anybody's guess what'll happen to these...
  12. */
  13.  
  14. #include "macwin.h"
  15.  
  16. #include <Memory.h>
  17. #include <Files.h>
  18. #include <Processes.h>
  19. #include <Errors.h>
  20. #include <AppleEvents.h>
  21. #include <AEObjects.h>
  22. #include <Desk.h>
  23.  
  24. #ifdef THINK_C
  25. /* XXX This is really only for versions that don't know about UPPs yet */
  26. #define NewAEEventHandlerProc(x) (x)
  27. #define AEEventHandlerUPP EventHandlerProcPtr
  28. #endif
  29.  
  30. static int in_wargs;        /* True while collecting arguments */
  31. L_DECLARE(wargs_argc, wargs_argv, char *);
  32.  
  33. /*
  34. ** Return FSSpec of current application.
  35. */
  36. static OSErr
  37. CurrentProcessLocation(FSSpec *applicationSpec)
  38. {
  39.         ProcessSerialNumber currentPSN;
  40.         ProcessInfoRec info;
  41.         
  42.         currentPSN.highLongOfPSN = 0;
  43.         currentPSN.lowLongOfPSN = kCurrentProcess;
  44.         info.processInfoLength = sizeof(ProcessInfoRec);
  45.         info.processName = NULL;
  46.         info.processAppSpec = applicationSpec;
  47.         return ( GetProcessInformation(¤tPSN, &info) );
  48. }
  49.  
  50. /*
  51. ** Given an FSSpec, return the FSSpec of the parent folder.
  52. */
  53. static OSErr
  54. GetFolderParent ( FSSpec * fss , FSSpec * parent ) {
  55.  
  56. CInfoPBRec rec ;
  57. short err ;
  58.  
  59.         * parent = * fss ;
  60.         rec . hFileInfo . ioNamePtr = parent -> name ;
  61.         rec . hFileInfo . ioVRefNum = parent -> vRefNum ;
  62.         rec . hFileInfo . ioDirID = parent -> parID ;
  63.         rec.hFileInfo.ioFDirIndex = -1;
  64.         rec . hFileInfo . ioFVersNum = 0 ;
  65.         if (err = PBGetCatInfoSync ( & rec ) )
  66.             return err;
  67.         parent -> parID = rec . dirInfo . ioDrParID ;
  68.       /*        parent -> name [ 0 ] = 0 ; */
  69.         return 0 ;
  70. }
  71.  
  72. /*
  73. ** Given an FSSpec return a full, colon-separated pathname
  74. */
  75. static OSErr
  76. GetFullPath ( FSSpec * fss , char *buf ) {
  77.     short err ;
  78.     FSSpec fss_parent, fss_current ;
  79.     char tmpbuf[256];
  80.     int plen;
  81.  
  82.     fss_current = *fss;
  83.     plen = fss_current.name[0];
  84.     memcpy(buf, &fss_current.name[1], plen);
  85.     buf[plen] = 0;
  86.     while ( fss_current.parID > 1 ) {
  87.                 /* Get parent folder name */
  88.                 if ( err =GetFolderParent( &fss_current , &fss_parent ) )
  89.                      return err;
  90.                 fss_current = fss_parent;
  91.                 /* Prepend path component just found to buf */
  92.                 plen = fss_current.name[0];
  93.                 if ( strlen(buf) + plen + 1 > 256 ) {
  94.                     /* Oops... Not enough space (shouldn't happen) */
  95.                     *buf = 0;
  96.                     return -1;
  97.                 }
  98.                 memcpy(tmpbuf, &fss_current.name[1], plen);
  99.                 tmpbuf[plen] = ':';
  100.                 strcpy(&tmpbuf[plen+1], buf);
  101.                 strcpy(buf, tmpbuf);
  102.         }
  103.         return 0 ;
  104. }
  105.  
  106. /*
  107. ** Return the full programname
  108. */
  109. static char *
  110. getappname()
  111. {
  112.     static char appname[256];
  113.     FSSpec appspec;
  114.     long size;
  115.     
  116.     if ( CurrentProcessLocation(&appspec) )
  117.         return NULL;
  118.     if ( GetFullPath(&appspec, appname) )
  119.         return NULL;
  120.     return appname;
  121. }
  122.  
  123. /* Check that there aren't any args remaining in the event */
  124. static OSErr 
  125. GetMissingParams( AppleEvent  *theAppleEvent)
  126. {
  127.     DescType    theType;
  128.     Size        actualSize;
  129.     OSErr        err;
  130.     
  131.     err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
  132.                                 &theType, nil, 0, &actualSize);
  133.     if (err == errAEDescNotFound)
  134.         return(noErr);
  135.     else
  136.         return(errAEEventNotHandled);
  137. }
  138.  
  139. /* Handle the "Open Application" event (by ignoring it) */
  140. static pascal
  141. OSErr HandleOpenApp(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
  142. {
  143.     #pragma unused (reply,refCon)
  144.     WindowPtr    window;
  145.     OSErr        err;
  146.     
  147.     err = GetMissingParams(theAppleEvent);
  148.     return(err);
  149. }
  150.  
  151. /* Handle the "Open Document" event, by adding an argument */
  152. static pascal
  153. OSErr HandleOpenDoc(AppleEvent *theAppleEvent, AppleEvent *reply, long refCon)
  154. {
  155.     #pragma unused (reply,refCon)
  156.     OSErr    err;
  157.     AEDescList doclist;
  158.     AEKeyword keywd;
  159.     DescType rttype;
  160.     long i, ndocs, size;
  161.     FSSpec fss;
  162.     char path[256];
  163.     
  164.     if ( !in_wargs )
  165.         return(errAEEventNotHandled);
  166.         
  167.     if ( err=AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &doclist) )
  168.         return err;
  169.     if (err = GetMissingParams(theAppleEvent)) 
  170.         return err;
  171.     if (err = AECountItems(&doclist, &ndocs) )
  172.         return err;
  173.     for(i=1; i<=ndocs; i++ ) {
  174.         err=AEGetNthPtr(&doclist, i, typeFSS, &keywd, &rttype, &fss, sizeof(fss), &size);
  175.         if ( err )
  176.             return err;
  177.         GetFullPath(&fss, path);
  178.         L_APPEND(wargs_argc, wargs_argv, char *, strdup(path));
  179.  
  180.     }
  181.     return(err);
  182. }
  183.  
  184. static pascal
  185. OSErr DummyHandler( AppleEvent        *theAppleEvent,
  186.                     AppleEvent        *reply,
  187.                     long            refCon    )
  188. {
  189.     #pragma unused (theAppleEvent,reply,refCon)
  190.     return(errAEEventNotHandled);
  191. }
  192.  
  193. void InitAEHandlers()
  194. {
  195.     AEEventHandlerUPP upp_opena = NewAEEventHandlerProc(HandleOpenApp);
  196.     AEEventHandlerUPP upp_opend = NewAEEventHandlerProc(HandleOpenDoc);
  197.     AEEventHandlerUPP upp_printd = NewAEEventHandlerProc(DummyHandler);
  198.     AEEventHandlerUPP upp_quit = NewAEEventHandlerProc(DummyHandler);
  199.     
  200.     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, upp_opena, 0L, false);
  201.     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, upp_opend, 0L, false);
  202.     AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, upp_printd, 0L, false);
  203.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, upp_quit, 0L, false);
  204. }
  205.  
  206.  
  207. static void 
  208. wargs_EventLoop()
  209. {
  210.     EventRecord        event;
  211.     int                gotEvent;
  212.     int                count = 0;
  213.  
  214.     do {
  215.         count++;
  216.         SystemTask();
  217.         gotEvent = GetNextEvent(everyEvent, &event);
  218.         if (gotEvent && event.what == kHighLevelEvent ) {
  219.             AEProcessAppleEvent(&event);
  220.         }
  221.     } while(  count < 100 );  /* Seems we get a few null events first... */
  222. }
  223.  
  224. void
  225. wargs(pargc, pargv)
  226.     int *pargc;
  227.     char ***pargv;
  228. {
  229.     char *apname;
  230.     
  231.     winit();
  232.     apname = getappname();
  233.     L_APPEND(wargs_argc, wargs_argv, char *, strdup(apname));
  234.     
  235.     in_wargs = 1;
  236.     InitAEHandlers();
  237.     wargs_EventLoop();
  238.     in_wargs = 0;
  239.  
  240.     *pargc = wargs_argc;
  241.     *pargv = wargs_argv;
  242. }
  243.  
  244.